#!/usr/bin/env python
# -*- coding: utf-8 -*-
##
#  Project: Kelindo - Unsupervised Music Organizer  
#  Author: Nicola Bicocchi <nicola.bicocchi@gmail.com>, Nicolo' Torreggiani <nicolo.torreggiani@gmail.com>, Gianluca Puglia <gianluca.puglia@gmail.com>, Matteo Senardi <pualien@gmail.com>
#  Copyright: 2013 Nicola Bicocchi, Nicolo' Torreggiani, Gianluca Puglia, Matteo Senardi
#  License: GPL-2+
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of the GNU General Public License as published by the Free
#  Software Foundation; either version 2 of the License, or (at your option)
#  any later version.
# 
#  This program is distributed in the hope that it will be useful, but WITHOUT
#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
#  more details.
# 
# On Debian GNU/Linux systems, the full text of the GNU General Public License
# can be found in the file /usr/share/common-licenses/GPL-2.
##

import gtk
import gobject
import threading
import urlparse

from kelindo import const
from kelindo.qltk.about import AboutDialog
from kelindo.qltk.details import Details
from kelindo.core.core import Kelindo

class Window(gtk.Window):    
    def __init__(self):
        super(Window, self).__init__()
        
        self.connect('destroy', lambda w: gtk.main_quit())
        self.connect('drag_motion', self.__motion_cb)
        self.connect('drag_drop', self.__drop_cb)
        self.connect('drag_data_received', self.__got_data_cb)
        self.set_position(gtk.WIN_POS_CENTER)
        self.drag_dest_set(gtk.DEST_DEFAULT_HIGHLIGHT, [], gtk.gdk.ACTION_DEFAULT)
        
        self.progress_bar = gtk.ProgressBar()
        self.progress_bar.set_size_request(350, 45)
        progress_box = gtk.HBox(False, 10)
        progress_box.pack_start(self.progress_bar, False, False, 10)
        
        self.status_bar = gtk.Statusbar()  
                
        main_box = gtk.VBox(False, 10)
        main_box.pack_start(self.generate_menubar(), False, False, 0)
        main_box.pack_start(progress_box, True, True, 0)
        main_box.pack_start(self.status_bar, False, False, 0)
        self.add(main_box)
        
        self.show_all()
        self.__update_interface()        
        self.running = False
        return
        
        
    def generate_menubar(self):
        menu_bar = gtk.MenuBar()
        file_menu = gtk.Menu()
        help_menu = gtk.Menu()
        file_menu_item = gtk.MenuItem("File")
        file_menu_item.set_submenu(file_menu)
        help_menu_item = gtk.MenuItem("About")
        help_menu_item.set_submenu(help_menu)
        
        open_item = gtk.MenuItem("Open...")
        open_item.connect("activate", self.__dst_folder_choose)
        file_menu.append(open_item)
       
        quit_item = gtk.MenuItem("Quit")
        quit_item.connect("activate", gtk.main_quit)
        file_menu.append(quit_item)
        
        help_item = gtk.MenuItem("Help")
        help_item.connect("activate", self.__help_dialog)
        help_menu.append(help_item)
       
        about_item = gtk.MenuItem("About")
        about_item.connect("activate", self.__about_dialog)
        help_menu.append(about_item)
        
        accel_group = gtk.AccelGroup()
        self.add_accel_group(accel_group)
        open_item.add_accelerator("activate", accel_group, ord('o'), gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)
        quit_item.add_accelerator("activate", accel_group, ord('q'), gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE)

        menu_bar.append(file_menu_item)
        menu_bar.append(help_menu_item)
        return menu_bar
        
    
    def __motion_cb(self, widget, context, x, y, time):
        context.drag_status(gtk.gdk.ACTION_COPY, time)
        if self.running:
            return False
        else:
            return True

    
    def __drop_cb(self, widget, context, x, y, time):
        widget.drag_get_data(context, context.targets[1], time)
        return True

    
    def __got_data_cb(self, widget, context, x, y, data, info, time):
        if data.get_data_type() == 'text/uri-list':
            uris = data.get_uris()
            self.path =  urlparse.urlparse(uris[0]).path
            self.path = self.path.replace('%20', ' ')
            context.finish(True, False, time)
        context.finish(False, False, time)
        
        # Folder dropped, process starts
        self.running = True
        self.core = Kelindo(self.path)
        self.core.subscribe(self.__core_callbacks)                
        t = threading.Thread(target=self.core.find_candidate_albums)
        t.daemon = True
        t.start()
        return

        
    def __core_callbacks(self, event):
        if event.key == 'candidate_no':
            gobject.idle_add(self.__show_dialog_candidate_no)
            return
            
        elif event.key == 'candidate_found':
            candidates = self.core.get_stats()['OK']
            gobject.idle_add(self.__update_statusbar, self.status_bar, 'Candidate %d/%d...' % (candidates, len(self.core.albums)))  
            gobject.idle_add(self.progress_bar.set_text, 'Step 1: Searching for candidates...')
            gobject.idle_add(self.progress_bar.pulse)            
            return
            
        elif event.key == 'candidate_done':  
            t = threading.Thread(target=self.core.classify_albums)
            t.daemon = True
            t.start()
            return
            
        elif event.key == 'album_started' or event.key == 'album_found':  
            gobject.idle_add(self.__update_interface,
                            'Candidate %d/%d...' % (event.done, event.total), 
                            float(event.done)/event.total,  
                            'Step 2: Classifying candidates...')
            return
            
        elif event.key == 'album_done':   
            gobject.idle_add(self.__show_dialog_details)
            return
            
        elif event.key == 'finalize_started' or event.key == 'finalize_track_done':
            gobject.idle_add(self.__update_interface,
                            'Track %d/%d...' % (event.done, event.total), 
                            float(event.done)/event.total,
                            'Step 3: Beautifying albums...')            
                                    
        elif event.key == 'finalize_done':
            gobject.idle_add(self.__update_interface,
                             'Done!')
            self.running = False
        return

        
    def __update_interface(self, status_bar='', progress=0.0, progress_txt='Drop some music here...'):
        self.__update_statusbar(self.status_bar, status_bar)
        self.progress_bar.set_fraction(progress)
        self.progress_bar.set_text(progress_txt)
        return

    
    def __update_statusbar(self, widget, str):
        context_id = widget.get_context_id('main_context')
        widget.remove_all(context_id)
        widget.push(context_id, str)
        return

        
    def __show_dialog_candidate_no(self):
        dialog = gtk.MessageDialog(parent=None, 
                                   flags=gtk.DIALOG_MODAL, 
                                   type=gtk.MESSAGE_WARNING, 
                                   buttons=gtk.BUTTONS_OK, 
                                   message_format='No candidate albums have been found here!')
        dialog.connect('response', self.__callback_dialog_candidate_no)
        dialog.show()
        return

            
    def __callback_dialog_candidate_no(self, dialog, response_id):
        if response_id == gtk.RESPONSE_OK:
            dialog.destroy()  
            self.running = False
            self.__update_interface()            
        return


    def __show_dialog_details(self):        
        self.dialog = Details(self.path, self.core.albums)
        self.dialog.connect('response', self.__callback_dialog_details)      
        self.dialog.show()
        return

        
    def __callback_dialog_details(self, dialog, response_id):
        if response_id == gtk.RESPONSE_ACCEPT: 
            root_dst_dir = dialog.combobox_dst.get_active_text()
            fmt = dialog.combobox_consolidate.get_active_text().lower()
            move_files = dialog.combobox_copy.get_active_text()
            if move_files == 'Move files':
                move_files = True
            else:
                move_files = False
            t = threading.Thread(target=self.core.finalize_albums, 
                                     args=(root_dst_dir, fmt, move_files))
            t.daemon = True
            t.start()
        else:           
            self.running = False            
            self.__update_interface()
        dialog.destroy()            
        return

    
    def __dst_folder_choose(self, widget):
        choose_dialog = gtk.FileChooserDialog("Choose Folder",None,gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        choose_dialog.set_default_response(gtk.RESPONSE_OK)
        response = choose_dialog.run()
        if response == gtk.RESPONSE_OK:
             self.path = choose_dialog.get_filename()
             self.running = True
             self.core = Kelindo(self.path)
             self.core.subscribe(self.__core_callbacks)                
             t = threading.Thread(target=self.core.find_candidate_albums)
             t.daemon = True
             t.start()
        choose_dialog.destroy()
        return


    def __about_dialog(self, widget):
        about_dialog = AboutDialog(self)
        about_dialog.run()
        about_dialog.destroy()
        
        
    def __help_dialog(self, parent):
        import webbrowser
        webbrowser.open(const.HELPSITE)